package com.goo.utils;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * java调用Linux下的shell命令工具
 */
public class ShellUtil {
    private static Logger log = LoggerFactory.getLogger(ShellUtil.class);
    // 基本路径
    private static final String basePath = "/nas/arfp/";
    // 记录Shell执行状况的日志文件的位置(绝对路径)
    private static final String executeShellLogFile = basePath + "executeShell.log";
    //链接超时时间
    private static int session_connect_timeout = 3000;
    //通道超时时间
    private static int channel_connect_timeout = 1000;
    //编码方式
    private static String charset = "UTF8";

    /**
     * @param shellCommand
     * @return
     * @throws IOException
     */
    public static String executeShell(String shellCommand) throws IOException {
        StringBuffer stringBuffer = new StringBuffer();
        BufferedReader bufferedReader = null;
        BufferedReader errorReader = null;
        // 格式化日期时间，记录日志时使用
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:SS ");
        StringBuffer result = new StringBuffer();

        try {
            stringBuffer.append(dateFormat.format(new Date()))
                    .append("准备执行Shell命令 ")
                    .append(shellCommand).append(" \r\n");
            Process process = null;
            String[] cmd = {"/bin/sh", "-c", shellCommand};
            // 执行Shell命令
            process = Runtime.getRuntime().exec(cmd);
            if (process != null) {
                stringBuffer.append("进程号：").append(process.toString()).append("\r\n");
                // bufferedReader用于读取Shell的输出内容
                bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()), 1024);
                errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()), 1024);
                process.waitFor();
            } else {
                stringBuffer.append("没有pid\r\n");
            }
            stringBuffer.append(dateFormat.format(new Date())).append("Shell命令执行完毕\r\n执行结果为：\r\n");
            String line = null;
            // 读取Shell的输出内容，并添加到stringBuffer中
            while (bufferedReader != null
                    && (line = bufferedReader.readLine()) != null) {
                stringBuffer.append(line).append("\r\n");
                result.append(line);
            }

            while (errorReader != null
                    && (line = errorReader.readLine()) != null) {
                stringBuffer.append(line).append("\r\n");
                result.append("execute fail:");
                result.append(line);
            }
        } catch (Exception ioe) {
            stringBuffer.append("执行Shell命令时发生异常：\r\n").append(ioe.getMessage()).append("\r\n");
        } finally {
            if (bufferedReader != null || errorReader != null) {
                OutputStreamWriter outputStreamWriter = null;
                try {
                    // 将Shell的执行情况输出到日志文件中
                    OutputStream outputStream = new FileOutputStream(executeShellLogFile, true);
                    outputStreamWriter = new OutputStreamWriter(outputStream, "UTF-8");
                    outputStreamWriter.write(stringBuffer.toString());
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    outputStreamWriter.close();
                }
            }

            if (bufferedReader != null) {
                IOUtils.closeQuietly(bufferedReader);
            }

            if (errorReader != null) {
                IOUtils.closeQuietly(errorReader);
            }
        }

        return result.toString();
    }


    /**
     * 利用JSch包实现远程主机SHELL命令执行
     *
     * @param ip         主机IP
     * @param user       主机登陆用户名
     * @param psw        主机登陆密码
     * @param port       主机ssh2登陆端口，如果取默认值，传-1
     * @param privateKey 密钥文件路径
     * @param passphrase 密钥的密码
     */
    public static void sshShell(String ip, String user, String psw
            , int port, String privateKey, String passphrase) throws Exception {

        JSch jsch = new JSch();
        //设置密钥和密码
        if (privateKey != null && !"".equals(privateKey)) {
            if (passphrase != null && "".equals(passphrase)) {
                //设置带口令的密钥
                jsch.addIdentity(privateKey, passphrase);
            } else {
                //设置不带口令的密钥
                jsch.addIdentity(privateKey);
            }
        }

        Session session = null;
        Channel channel = null;
        if (port <= 0) {
            //连接服务器，采用默认端口
            session = jsch.getSession(user, ip);
        } else {
            //采用指定的端口连接服务器
            session = jsch.getSession(user, ip, port);
        }
        //如果服务器连接不上，则抛出异常
        if (session == null) {
            throw new Exception("session is null");
        }

        //设置登陆主机的密码
        session.setPassword(psw);//设置密码
        //设置第一次登陆的时候提示，可选值：(ask | yes | no)
        session.setConfig("StrictHostKeyChecking", "no");
        //设置登陆超时时间
        session.connect(session_connect_timeout);

        try {
            //创建sftp通信通道
            channel = (Channel) session.openChannel("shell");
            channel.connect(channel_connect_timeout);

            //获取输入流和输出流
            InputStream instream = channel.getInputStream();
            OutputStream outstream = channel.getOutputStream();

            //发送需要执行的SHELL命令，需要用\n结尾，表示回车
            String shellCommand = "cd /home; ls \n";
            outstream.write(shellCommand.getBytes());
            outstream.flush();

            //获取命令执行的结果
            int available = instream.available();
            if (available > 0) {
                byte[] data = new byte[available];
                int nLen = instream.read(data);

                if (nLen < 0) {
                    throw new Exception("network error.");
                }

                //转换输出结果并打印出来
                // String temp = new String(data, 0, nLen,"UTF-8");
                String tempData = new String(data, charset);
                 System.out.println(tempData);
                log.info(tempData);
            }
            outstream.close();
            instream.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            session.disconnect();
            channel.disconnect();
        }
    }

    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {

        // String fileName = args[0];
        // 调用shell命令上传文件
        String cmd = "aftstcp 1 ABISFILE %s 01@000";
        // String result = ShellUtil.executeShell(String.format(cmd, fileName));
//        ShellUtil.sshShell("ip", "用户名", "密码", 22, null, null);
        ShellUtil.sshShell("8.135.42.12", "root", "Dszn@2020", 22, null, null);

    }
}

